home *** CD-ROM | disk | FTP | other *** search
- ; PatchZeus.asm - resident module to patch PPI Zeus SCSI driver
- ;
- ; Written by Michael L. Hitch
- ; Montana State University
- ; osymh@msu.oscs.montana.edu
- ;
-
- include "exec/types.i"
- include "exec/nodes.i"
- include "exec/memory.i"
- include "exec/resident.i"
- include "exec/execbase.i"
- include "exec/libraries.i"
- include "exec/io.i"
- include "exec/errors.i"
- include "devices/scsidisk.i"
- include "libraries/configvars.i"
- include "libraries/expansion.i"
- include "hardware/cia.i"
- include "hardware/custom.i"
-
- ; xref _LVOOpenLibrary
- ; xref _LVOCloseLibrary
- ; xref _LVOFindConfigDev
- xref _LVOAllocSignal
- xref _LVOFreeSignal
- xref _LVOFindTask
- xref _LVOFindName
- xref _LVOSignal
- xref _LVOWait
- xref _LVOAllocMem
- xref _LVOSumKickData
- xref _LVOForbid
- xref _LVOPermit
- xref _LVODisable
- xref _LVOEnable
- xref _LVOSupervisor
- xref _LVOCacheControl
- xref _ciaa
- xref _custom
-
- csect text
- ;
- ; Program entry point
- ;
- movem.l d2-d3/a2/a5/a6,-(sp)
- move.l 4,a6
- ;
- ; *** process command line arguments
- ;
- jsr AddResident(pc) ; Add program to KickMemPtr list
- ;*** check status?
- ;
- movem.l (sp)+,d2-d3/a2/a5/a6
- rts
- ;
- ;
- AddResident
- move.l KickMemPtr(a6),a0
- 1$:
- move.l a0,d0
- beq.s NewResident ; Not found
- move.l LN_NAME(a0),a1 ; name of this entry
- lea TagName(pc),a2 ; my name
- 2$:
- move.b (a1)+,d0
- cmp.b (a2)+,d0
- bne.s 3$
- tst.b d0
- bne 2$
- ; found entry
- moveq #1,d0
- rts
- 3$:
- move.l (a0),a0 ; Next entry
- bra 1$
- ;
- ; Layout of memory block
- ; ds.b 8 Overhead space for AllocAbs
- ; ds.b ML_SIZE Memory entry list
- ; ds.b ME_SIZE Memory entry
- ; ds.b 8 RomTab pointer array
- ; ds.b nnn Resident module
- ;
- KM_RTPTR equ ML_SIZE+ME_SIZE ; Location of RomTag pointer array
- KM_SIZE equ KM_RTPTR+8 ; Size of KickMem info header
- ;
- NewResident:
- moveq #KM_SIZE+8,d0 ; size of KickMem header + 8 byte overhead
- add.l RomTag+6(pc),d0
- sub.l RomTag+2(pc),d0 ; add length of resident module
- move.l #MEMF_24BITDMA!MEMF_CLEAR,d1
- jsr _LVOAllocMem(a6) ; allocate memory
- tst.l d0
- bne.s 1$
- moveq #KM_SIZE+8,d0 ; size of KickMem header + 8 byte overhead
- add.l RomTag+6(pc),d0
- sub.l RomTag+2(pc),d0 ; add length of resident module
- move.l #MEMF_CHIP!MEMF_CLEAR,d1
- jsr _LVOAllocMem(a6) ; allocate memory
- tst.l d0
- bne.s 1$
- moveq #2,d0
- rts
- 1$:
- move.l d0,a0 ; a0 = address of allocated memory
- lea 8(a0),a2 ; a2 = address of MemList
- move.b #NT_MEMORY,LN_TYPE(a2) ; initialize MemList
- move.w #1,ML_NUMENTRIES(a2)
- move.l a0,ML_ME(a2)
- moveq #KM_SIZE+8,d0 ; size of KickMem header + 8 byte overhead
- move.l d0,ML_ME+ME_LENGTH(a2)
- move.l RomTag+6(pc),d0
- sub.l RomTag+2(pc),d0 ; d0 = length of resident module
- add.l d0,ML_ME+ME_LENGTH(a2)
- lea KM_SIZE+8(a0),a0 ; point to RomTag structure
- lea RomTag(pc),a1
- move.l a0,d1
- sub.l a1,d1 ; relocation offset for RomTag addresses
- move.l a0,KM_RTPTR(a2) ; RomTag Pointer
- subq.l #1,d0
- 2$: move.b (a1)+,(a0)+ ; copy resident module
- dbra d0,2$
- move.l KM_RTPTR(a2),a0 ; Point to RomTag structure
- add.l d1,RT_MATCHTAG(a0) ; relocate absolute addresses
- add.l d1,RT_ENDSKIP(a0)
- add.l d1,RT_NAME(a0)
- add.l d1,RT_IDSTRING(a0)
- add.l d1,RT_INIT(a0)
- move.l RT_NAME(a0),LN_NAME(a2) ; set MemList name same as RomTag name
- ;*** add to KickMemPtr & KickTagPtr
- jsr _LVOForbid(a6)
- lea KickMemPtr(a6),a0
- 3$: move.l (a0),d0
- beq.s 4$
- move.l d0,a0
- bra 3$
- 4$: tst.l KickMemPtr(a6)
- beq.s 5$
- move.l a0,LN_PRED(a2) ; is this really needed?
- move.l a2,(a0)
- bra.s 6$
- 5$: move.l a2,KickMemPtr(a6)
- 6$: move.l KickTagPtr(a6),d0
- beq.s 7$
- bset #31,d0
- move.l d0,KM_RTPTR+4(a2) ; link to existing RomTag pointer array
- 7$: lea KM_RTPTR(a2),a0 ; address of our RomTag pointer array
- move.l a0,KickTagPtr(a6)
- jsr _LVOSumKickData(a6)
- move.l d0,KickCheckSum(a6)
- jsr _LVOPermit(a6)
- ;*** call resident initialization routine?
- lea myClearCache(pc),a5 ; clear caches before executing
- jsr _LVOSupervisor(a6) ; the initialization code
- move.l KM_RTPTR(a2),a0
- move.l RT_INIT(a0),a0
- jsr (a0) ; Call initialization routine
- moveq #0,d0
- rts
- ;
- myClearCache:
- cpusha bc ; push and invalid both caches
- rte
- ;
- ;
- ; The resident RomTag structure
- ;
- RomTag: dc.w RTC_MATCHWORD
- dc.l RomTag
- dc.l EndModule
- dc.b RTF_COLDSTART
- dc.b 37
- dc.b NT_KICKMEM
- dc.b 0
- dc.l TagName
- dc.l TagID
- dc.l TagInit
-
- TagName: dc.b "PatchZeus",0
- dc.b "$VER: "
- TagID: dc.b "PatchZeus 1.1 (26.10.93)",$0d,$0a,0
- ZeusName: dc.b "PPSscsi2.device",0
- ExpName: EXPANSIONNAME
- ds.w 0
-
- PATCHLOC1 equ $19b0 ; setup prior to starting 53C710 script
- PATCHLOC2 equ $1a38 ; wait for 53C710 completion
- PATCHLOC3 equ $1f88 ; Interrupt - signal completion
- PATCHLOC4 equ $1ff8 ; Interrupt - phase mismatch
- PATCHLOC5 equ $20ee ; 53C170 setup - set SCNTL0
- PATCHLOC6 equ $210c ; 53C710 setup - set SIEN
- PATCHLOC7 equ $1d32 ; Interrupt - received interrupt
- PATCHLOC8 equ $28ae ; SCSIcmd - adjust scsi_Actual
- PATCHLOC9 equ $28a0 ; SCSIcmd - adjust scsi_SenseActual
- PATCHLOC10 equ $0ef0 ; Compare partition name with BSTR name
- PATCHLOC11 equ $1ec0 ; Interrupt - code $ff01
- PATCHLOC12 equ $136c ; Device Open - return HFERR_NoBoard
- PATCHLOC13 equ $27fc ; ScsiCmd - return HFERR_BadStatus
- PATCHLOC14 equ $1b5a ; Sync request period
-
- ;
- ; Entry when resident module is initialized
- ;
- TagInit:
- movem.l d2/d3/a2/a4,-(sp)
- lea _custom,a0 ; Address of custom chip
- move.w potinp(a0),d0 ; Read register
- ori.w #$0c00,d0 ; Set output, data = 1
- move.w d0,potgo(a0)
- move.w potinp(a0),d0 ; Read data
- andi.w #$0400,d0 ; Test if Mouse right button pressed
- beq.s SkipMouse ; Yes, don't check left button
- lea _ciaa,a0
- btst #6,ciapra(a0) ; Test if Mouse left button pressed
- beq.s TagExit ; Yes, skip it
- SkipMouse:
- btst #AFB_68040,AttnFlags+1(a6) ; is it 68040?
- bne.s Is_68040
- cmp.w #36,LIB_VERSION(a6) ; if version 2.0 or later
- bge.s TagExit ; then AFB_68040 is valid
- ; *** 68040 not detected on WB1.3
- moveq #AFF_68030!AFF_68020,d0
- and.w AttnFlags(a6),d0 ; Kludge for WB1.3
- bne.s Is_68040
- TagExit:
- moveq #0,d0
- movem.l (sp)+,d2/d3/a2/a4
- rts
-
- Is_68040:
- lea DeviceList(a6),a0 ; get address of device list
- lea ZeusName(pc),a1 ; Device driver name
- jsr _LVOFindName(a6) ; Find device driver
- tst.l d0
- beq TagExit ; Didn't find it
- move.l d0,a2
- ;
- ; Found device driver; make sure it's the correct version and validate
- ; the places we are going to patch
- ;
- bra.s debug1 ; ** DEBUG ** nop to enable color changes
- move.w #$00ff,$00dff180 ; ** DEBUG ** set screen color = cyan
- move.l #$00800000,d0
- delay1: subq.l #1,d0
- bgt delay1
- move.w #$0888,$00dff180
- debug1:
- cmp.w #98,LIB_REVISION(a2) ; Check if revision 98
- bne TagExit ; Nope, skip it
- move.l LN_NAME(a2),a4
- lea -$521(a4),a4 ; Base relative to start of ROM
- cmp.l #$584f206d,PATCHLOC1(a4) ; verify patch points
- bne TagExit
- cmp.l #$206d0008,PATCHLOC2(a4)
- bne TagExit
- cmp.l #$217c0000,PATCHLOC3(a4)
- bne TagExit
- cmp.l #$02800000,PATCHLOC4(a4)
- bne TagExit
- cmp.l #$117c00cc,PATCHLOC5(a4)
- bne TagExit
- cmp.l #$10bc00bf,PATCHLOC6(a4)
- bne TagExit
- cmp.l #$02800000,PATCHLOC7(a4)
- bne TagExit
- cmp.l #$23680004,PATCHLOC8(a4)
- bne TagExit
- cmp.l #$3368001a,PATCHLOC9(a4)
- bne TagExit
- cmp.l #$e5802b40,PATCHLOC10(a4)
- bne TagExit
- cmp.l #$20280030,PATCHLOC11(a4)
- bne TagExit
- cmp.l #$0cad0000,PATCHLOC12(a4)
- bne TagExit
- cmp.l #$2b7c0000,PATCHLOC13(a4)
- bne TagExit
- cmp.l #$001e0104,PATCHLOC14(a4)
- bne TagExit
- bra.s debug2 ; ** DEBUG ** nop to enable color changes
- move.w #$0f0f,$00dff180 ; ** DEBUG ** set screen color = magenta
- move.l #$00800000,d0
- delay2: subq.l #1,d0
- bgt delay2
- move.w #$0888,$00dff180
- debug2:
- ;
- ; install patches
- ;
- ; relocate jumps back into the driver
- ;
- move.l a4,d0
- lea Patch1end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch2end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch3end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch4end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch7end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch8end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch9end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch10end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch11end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch11end2(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch12end(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- lea Patch12end2(pc),a0
- move.l (a0),-(a0)
- add.l d0,(a0)
- ;
- ; patch new code into the driver
- ;
- lea Patch1(pc),a0 ; setup prior to starting 53C710 script
- move.w #$4ef9,PATCHLOC1(a4)
- move.l a0,PATCHLOC1+2(a4)
- lea Patch2(pc),a0
- move.w #$4ef9,PATCHLOC2(a4) ; wait for 53C710 completion
- move.l a0,PATCHLOC2+2(a4)
- lea Patch3(pc),a0
- move.w #$4ef9,PATCHLOC3(a4) ; Interrupt - signal waiting task
- move.l a0,PATCHLOC3+2(a4)
- lea Patch4(pc),a0
- move.w #$4ef9,PATCHLOC4(a4) ; Interrupt - phase mismatch
- move.l a0,PATCHLOC4+2(a4)
- ; move.w #$00c4,PATCHLOC5+2(a4) ; don't check parity
- ; move.w #$00be,PATCHLOC6+2(a4) ; don't interrupt on parity
- ; move.b #$c4,$e94003
- ; move.b #$be,$e94000
- lea Patch7(pc),a0 ; Interrupt - save 52C710 info for debug
- move.w #$4ef9,PATCHLOC7(a4)
- move.l a0,PATCHLOC7+2(a4)
- lea Patch8(pc),a0 ; SCSIcmd - adjust scsi_Actual
- move.w #$4ef9,PATCHLOC8(a4)
- move.l a0,PATCHLOC8+2(a4)
- lea Patch9(pc),a0 ; SCSIcmd - adjust scsi_SenseActual
- move.w #$4ef9,PATCHLOC9(a4)
- move.l a0,PATCHLOC9+2(a4)
- lea Patch10(pc),a0 ; Compare partition name with BSTR name
- move.w #$4ef9,PATCHLOC10(a4)
- move.l a0,PATCHLOC10+2(a4)
- lea Patch11(pc),a0 ; Interrupt - code $ff01
- move.w #$4ef9,PATCHLOC11(a4)
- move.l a0,PATCHLOC11+2(a4)
- lea Patch12(pc),a0 ; Return HFERR_NoBoard on device open
- move.w #$4ef9,PATCHLOC12(a4)
- move.l a0,PATCHLOC12+2(a4)
- move.w #HFERR_BadStatus,PATCHLOC13+4(a4) ; SCSIcmd - return HFERR_BadSTatus
- move.w #100/4,PATCHLOC14(a4) ; negotiate for 100usec period
- lea 510(a2),a0 ; Initialize unused command
- lea Cmd_Invalid(pc),a1 ; entries in dispatch vector
- moveq #31,d0
- 1$: tst.l (a0)
- bne.s 2$ ; this entry defined
- move.l a1,(a0)
- 2$: addq.l #4,a0
- dbra d0,1$
- ; to do: patch new command routines
- move.w #9850,LIB_REVISION(a2) ; Change revision to 985x
- moveq #1,d0
- movem.l (sp)+,d2/d3/a2/a4
- rts
-
- ;
- ; Prior to starting 53C710 script execution, initialize task pointer and
- ; allocate a signal
- ; Also, turn off data cache if buffer does not start and stop on a quadword
- ; boundary
- ;
- Patch1:
- addq.w #4,sp ; restore stack
- move.l -8(a5),a0 ; Unit pointer
- move.l 468+20(a0),d0 ; data length
- add.l 468+24(a0),d0 ; + data start -> buffer end
- or.l 468+24(a0),d0 ; | data start
- and.l #15,d0 ; Flag if buffer not quadword boundary
- move.l d0,-(sp) ; save flag
- move.l d0,-(sp) ; save old cache settings
- move.l a6,-(sp)
- move.l 4,a6
- tst.l d0 ; test flag
- beq.s 1$ ; buffer starts and stops on quadword boundary
- moveq #0,d0 ; Turn off data cache
- move.l #CACRF_EnableD,d1
- jsr _LVOCacheControl(a6)
- move.l d0,4(sp) ; save previous cache settings
- 1$:
- sub.l a1,a1
- jsr _LVOFindTask(a6) ; get our task pointer
- move.l 8(a5),a0 ; device pointer
- move.l d0,92(a0) ; save task pointer
- moveq #-1,d0
- jsr _LVOAllocSignal(a6) ; allocate available signal
- move.l (sp)+,a6
- move.l 8(a5),a0
- move.l d0,96(a0) ; save signal number
- clr.l 100(a0) ; clear DBC
- move.l 12(a5),a1 ; ***** Debug: get IOR pointer
- move.l IO_UNIT(a1),34(a0) ; ***** Debug: save last unit pointer
- jmp $800019b6
- Patch1end:
- dc.l $000019b6
-
- ;
- ; Wait for signal from interrupt server and free signal
- ;
- Patch2:
- move.l 8(a5),a0
- move.l 96(a0),d1 ; get signal number
- moveq #1,d0
- lsl.l d1,d0 ; form mask
- move.l a6,-(sp)
- move.l 4,a6
- jsr _LVOWait(a6) ; Wait for signal
- move.l 8(a5),a0
- move.l 96(a0),d0
- jsr _LVOFreeSignal(a6) ; free the signal
- move.l (sp)+,a6
- move.l (sp)+,d0 ; get previous cache settings
- move.l (sp)+,d1 ; get flag
- beq.s 1$ ; if data cache was turned off,
- move.l #CACRF_EnableD,d1
- move.l a6,-(sp)
- move.l 4,a6
- jsr _LVOCacheControl(a6) ; restore previous cache settings
- move.l (sp)+,a6
- 1$:
- jmp $80001a46
- Patch2end:
- dc.l $00001a46
-
- ;
- ; When 53C710 has completed, signal waiting task (if any)
- ;
- Patch3:
- move.l #1,84(a0) ; set flag [redundant now]
- move.l 92(a0),d0
- beq.s 1$ ; skip if no task pointer
- move.l d0,a1
- move.l 96(a0),d1
- moveq #1,d0
- lsl.l d1,d0 ; form signal number
- move.l a6,-(sp)
- move.l 4,a6
- jsr _LVOSignal(a6) ; signal the waiting task
- move.l (sp)+,a6
- 1$:
- jmp $80001f90
- Patch3end:
- dc.l $00001f90
-
- ;
- ; Phase mismatch, store SBCL register in circular buffer
- ; Also, if phase == STATUS, save DBC for adjustment of data transfer length
- ;
- Patch4:
- move.l 8(a5),a0 ; Device pointer
- moveq #0,d1
- move.b 43(a0),d1 ; buffer index
- move.b d0,44(a0,d1) ; store SBCL value
- addq.w #1,d1 ; increment index
- andi.w #$000f,d1 ; wrap around
- move.b d1,43(a0)
- moveq #7,d1
- and.l d1,d0 ; mask phase bits
- cmpi.b #3,d0 ; is phase STATUS?
- bne.s 1$
- ; move.l 104(a0),100(a0) ; isolate DBC
- move.l $e94024,100(a0) ; get dcmd/dbc */
- clr.b 100(a0)
- 1$:
- jmp $80002088
- Patch4end:
- dc.l $00002088
-
- ;
- ; Debug stuff - save DSTAT & SSTAT0 in circular buffer on interrupt
- ; also save DCMD/DBC and DSP
- ;
- Patch7:
- andi.l #$ff,d0 ; replaced instruction
- move.b d0,-14(a5) ; store DSTAT
- move.l -4(a5),a0 ; load Device pointer
- moveq #0,d1
- move.b 42(a0),d1 ; buffer index
- move.b d0,60(a0,d1) ; store DSTAT in buffer
- move.b -19(a5),61(a0,d1) ; store SSTAT0 in buffer
- addq.w #2,d1
- andi.w #15,d1
- move.b d1,42(a0) ; update buffer index
- move.l $e94024,104(a0) ; save DCMD/DBC
- move.l $e9402c,108(a0) ; save DSP
- jmp $80001d3c
- Patch7end:
- dc.l $00001d3c
-
- ;
- ; SCSI_cmd - set scsi_Actual correctly
- ;
- Patch8:
- move.l 4(a0),8(a1) ; scsi_Actual = scsi_Length
- move.l -12(a5),a0 ; Unit pointer
- move.l 2066(a0),a0 ; Device pointer
- move.l 100(a0),d0 ; get DBC
- sub.l d0,8(a1) ; adjust scsi_Actual
- jmp $800028b4
- Patch8end:
- dc.l $000028b4
-
- ;
- ; SCSI_cmd - set scsi_Sense_Actual correctly
- ;
- Patch9:
- move.w 26(a1),28(a0) ; scsi_SenseActual = scsi_SenseLength
- move.l -12(a5),a1 ; Unit pointer
- move.l 2066(a1),a1 ; Device pointer
- move.l 100(a1),d0 ; get DBC
- sub.w d0,28(a0) ; adjust scsi_Actual
- move.l 4(a0),100(a1) ; set DBC = scsi_Length so scsi_Actual
- jmp $800028a6 ; will get set to zero
- Patch9end:
- dc.l $000028a6
-
- ;
- ; Compare RDB name to Device Node BSTR name
- ;
- Patch10:
- asl.l #2,d0 ; convert BSTR pointer to address
- addq.l #1,d0 ; skip count byte
- move.l d0,-16(a5)
- jmp $80000ef6
- Patch10end:
- dc.l $00000ef6
-
- ;
- ; Interrupt code $ff01 - Phase not MsgOut after selection
- ;
- Patch11:
- move.l 48(a0),d0 ; load DSPS
- cmpi.l #$0000ff01,d0 ; is it Phase not MsgOut after selection?
- beq.s Patch11b ; yes, check current phase
- Patch11a:
- jmp $80001f0c ; continue
- Patch11end:
- dc.l $00001f0c
- Patch11b:
- move.b 8(a0),d1 ; get SBCL
- andi.b #$07,d1 ; mask off phase
- cmpi.b #$02,d1 ; is it Command Out?
- bne.s Patch11a ; no, continue
- ; andi.b #$f7,4(a0) ; <reset ATN?>
- lea -32602(a4),a1 ; restart script processing for command out
- move.l a1,44(a0) ; DSPS
- clr.b -18(a5) ; clear flag to signal completion
- jmp $80001f24 ; (we aren't done yet)
- Patch11end2:
- dc.l $00001f24
-
- ;
- ; Device Open - return HFERR_NoBoard if unit number >= 100
- ;
- Patch12:
- move.l -16(a5),d0 ; get unit number
- cmpi.l #8,d0
- bhs.s Patch12a ; it's not valid
- jmp $80001386
- Patch12end:
- dc.l $00001386
- Patch12a:
- moveq #HFERR_NoBoard,d1 ; return error
- cmpi.l #100,d0
- bhs.s Patch12b
- moveq #IOERR_OPENFAIL,d1
- Patch12b:
- move.l -8(a5),a0
- move.b d1,IO_ERROR(a0)
- jmp $80001450
- Patch12end2:
- dc.l $00001450
-
- ;
- ; Invalid commands - return error code
- ;
- Cmd_Invalid:
- move.l 4(sp),a0 ; Get IOR pointer
- moveq #IOERR_NOCMD,d0 ; set error code
- move.b d0,IO_ERROR(a0)
- clr.l IO_ACTUAL(a0) ; clear io_Actual
- rts
-
- EndModule:
-
- end
-